package com.atguigu.tingshu.album.task;

import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author: atguigu
 * @create: 2025-06-11 10:19
 */
@Slf4j
@Component
public class RebuildBloomFilterTask {


    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private AlbumInfoService albumInfoService;

    /**
     * 公告：每月1号凌晨2~3点项目维护，避免数据不一致
     * 每月1号2点：重建布隆过滤器
     */
    @Scheduled(cron = "0 0 2 1 * ?")
    //@Scheduled(cron = "0/5 * * * * ?")
    public void rebuildBloomFilter() {
        //1.获取现有布隆过滤器对象，得到配置信息：1.期望数据规模  2.误判率 3.现有元素数量(预估值)
        RBloomFilter<Long> oldBloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        long expectedInsertions = oldBloomFilter.getExpectedInsertions();
        double falseProbability = oldBloomFilter.getFalseProbability();
        long count = oldBloomFilter.count();
        //2.判断是否满足扩容条件：现有元素数量大于等于期望数据规模
        if (count >= expectedInsertions) {
            log.info("满足扩容条件，开始扩容重建...");
            //2.1 先初始化新的布隆过滤器，原有期望数据规模*2
            RBloomFilter<Long> newBloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER + ":new");
            if (!newBloomFilter.isExists()) {
                newBloomFilter.tryInit(expectedInsertions * 2, falseProbability);
                //2.2 将数据中先有合法专辑ID加入到新的布隆过滤器中
                List<AlbumInfo> list = albumInfoService.list(
                        new LambdaQueryWrapper<AlbumInfo>()
                                .eq(AlbumInfo::getStatus, SystemConstant.ALBUM_STATUS_PASS)
                                .select(AlbumInfo::getId)
                );
                for (AlbumInfo albumInfo : list) {
                    newBloomFilter.add(albumInfo.getId());
                }
                //2.3 删除旧的布隆过滤器:布隆过滤器配置及位图
                oldBloomFilter.delete();
                //2.4 重命名布隆过滤器，改为原来名称
                newBloomFilter.rename(RedisConstant.ALBUM_BLOOM_FILTER);
            }
        } else {
            log.info("不满足扩容条件，开始重建...");
            //3.不满足扩容条件，做基本重建:  1.初始化布隆过滤器 2.将数据中先有合法专辑ID加入到布隆过滤器中 3.重命名布隆过滤器，改为原来名称 4.删除旧的布隆过滤器
            //3.1 先初始化新的布隆过滤器
            RBloomFilter<Long> newBloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER + ":new");
            newBloomFilter.tryInit(expectedInsertions, falseProbability);
            //3.2 将数据中先有合法专辑ID加入到新的布隆过滤器中
            List<AlbumInfo> list = albumInfoService.list(
                    new LambdaQueryWrapper<AlbumInfo>()
                            .eq(AlbumInfo::getStatus, SystemConstant.ALBUM_STATUS_PASS)
                            .select(AlbumInfo::getId)
            );
            for (AlbumInfo albumInfo : list) {
                newBloomFilter.add(albumInfo.getId());
            }
            //3.3 删除旧的布隆过滤器:布隆过滤器配置及位图
            oldBloomFilter.delete();
            //3.4 重命名布隆过滤器，改为原来名称
            newBloomFilter.rename(RedisConstant.ALBUM_BLOOM_FILTER);
            log.info("布隆过滤器重建完成...");
        }
    }
}
